package gates;

import java.awt.Graphics;

import master.*;

/**
 * 
 * A functional representation of the Hadamard gate, made so it can act on any size register, and any bit
 * 
 * @author Matthew
 *
 */
public class Hadamard implements QuantumGate {

	
	private static IllegalArgumentException
	bitException = new IllegalArgumentException("The register is not big enough to work on that bit");

	private int dim;
	private int N;
	ComplexNumber[] a;
	
	
	public Hadamard(int N){
		
		
		this.N = N;
		
		dim = (int)Math.pow(2, N);
		a = new ComplexNumber[dim];
		
		
	}
	
	public QuantumRegister actOnReg (QuantumRegister register, int bit){
		
		if (bit >= N ){
			throw bitException; 
			
		}

		//method to act the gate on the register
		
		//create a temporary array
		float temp = (float) (1 / Math.sqrt(2));
		
		for (int i = 0; i < dim; i ++){
			a[i] = new ComplexNumber();
		}
		

		for(int i=0; i < dim; i ++){

			
			/**
			 *
			 *create a temporary variable, storing the value of the current element of the register
			 *example, register in state |1>, = (0,1), this changes it to (0,-1)
			 *and creates temporary vector (1,0) 
			 * 
			 */
			if (register.getCoefficient(i).getReal() != new ComplexNumber().getReal()){
							
				
				ComplexNumber complexTemp = new ComplexNumber(register.getCoefficient(i).getReal(), register.getCoefficient(i).getImaginary()); 
			 	a[i^bit] = complexTemp;

			 	//if the qubit is a 1, set it to -ve 1, otherwise leave it
			 	if (i > (i^bit)){
					ComplexNumber z = register.getCoefficient(i).multByNo(-1);
					register.setCoefficient(z, i);
				}

			}
		}
		
	/**
	 *make the register the sum of its current value, plus the temporary array
	 *created to hold the "other" bit made by the hadamard bit, continueing the example above
	 *this part of code adds the register and the temporary array together, giving (1,-1) and then
	 *multiplies by 1/sqrt(2), giving H |1 > = 1/sqrt(2) (|0> - |1>)
	 * 
	 * 
	 */
		
		
		for (int j =0; j < dim; j++){
//			System.out.println(j + " " + register.getCoefficient(j) +  " + " + a[j]);
	//		System.out.println(register.getCoefficient(j));
			ComplexNumber temp1 = register.getCoefficient(j).add(a[j]); 
			temp1 = temp1.multByNo(temp);
//			System.out.println("" + temp1);
			register.setCoefficient(temp1, j);		
		}
			
			

		return register;
	}
		
		
		
		
	

	public boolean checkDim(QuantumRegister register){
		//checks dimensions of quantum register and compares with dimensions of matrix
		if (register.getDimension() == dim){
			return true;
		}else{
			return false;
		}
	

	}

	@Override
	public QuantumRegister actOnReg(QuantumRegister register, int bit1, int bit2) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QuantumRegister actOnReg(QuantumRegister register, int bit1,
			int bit2, int bit3) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QuantumGate multiply(QuantumGate gate) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void draw(Graphics g, int x, int y, float scale) {
		// TODO Auto-generated method stub
		
	}
	
}
